<template>
  <div class="page-view">
    <!-- 顶部站点切换和导出 -->
    <SiteAndExport @changeSite="handleChangeSite" :params="params" :interface="'getPvAndUv'" :chartInstances="[myChart]" />
    <!-- 时间选择 -->
    <div class="date-select">
      <div class="select-left">
        <span>时间范围：</span>
        <TypeSelect v-model:value="dateType" :typeList="dateTypeList" />
        <el-date-picker v-model="dateRange" type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" class="date-picker" />
      </div>
      <div class="select-right">
        <TypeSelect v-model:value="xAxisType" :typeList="xAxisTypeList" />
      </div>
    </div>
    <!-- 图文展示 -->
    <div class="data-content" v-loading="tableLoading">
      <div class="data-card">
        <div class="card-item" v-for="(v, k) in dataLabel" :key="k">
          <span class="label">{{ v }}</span>
          <span class="num">{{ overview[k] }}</span>
        </div>
      </div>
      <div class="chart-header">
        <div class="point-select">
          <span>显示指标：</span>
          <el-checkbox-group v-model="checkList">
            <el-checkbox v-for="(item, index) in checkOptions" :key="index" :label="item.value">{{ item.label }}</el-checkbox>
          </el-checkbox-group>
        </div>
        <div class="chart-btns">
          <el-tooltip content="趋势图" placement="bottom" effect="light">
            <a :class="{ active: chartType === 'line' }" href="javascript:;" @click="changeChart('line', false)"><i class="iconfont">&#xe700;</i></a>
          </el-tooltip>
          <el-tooltip content="柱图" placement="bottom" effect="light">
            <a :class="{ active: chartType === 'bar' }" href="javascript:;" @click="changeChart('bar', true)"><i class="iconfont">&#xe703;</i></a>
          </el-tooltip>
        </div>
      </div>
      <div ref="chart" style="width: 100%; height: 300px" id="export-chart"></div>
    </div>
    <!-- 表格展示 -->
    <div class="table-content">
      <RuifoxTable :loading="tableLoading" :default-index="true" v-model:tableData="tableData" v-model:fieldList="fieldList">
        <template #visitorPercent="{ element }">
          {{ element.visitorPercent + '%' }}
        </template>
        <template #viewPercent="{ element }">
          {{ element.viewPercent + '%' }}
        </template>
      </RuifoxTable>
    </div>
  </div>
</template>

<script setup>
/* eslint-disable */
import { onMounted, ref, reactive, watch } from 'vue'
import TypeSelect from './components/TypeSelect.vue'
import SiteAndExport from './components/SiteAndExport.vue'
import echarts from '@/utils/echarts'
import { getStationPvAndUv } from '@/api/log'
import { getStartAndEndTimes, getTimeDifference } from '@/utils/tools'
import dayjs from 'dayjs'
import { useStore } from 'vuex'

const store = useStore()
//查询时间选择
const dateType = ref(0)
const dateTypeList = ref([
  { value: 0, label: '今日' },
  { value: 1, label: '昨日' },
  { value: 2, label: '近7日' },
  { value: 3, label: '近30天' }
])
//图表x轴类型选择
const xAxisType = ref(0)
const xAxisTypeList = ref([
  { value: 0, label: '按时', disabled: false },
  { value: 1, label: '按日', disabled: true }
])
//自定义时间段。有时间就查时间段，没时间就查整天或整月...dateType
const dateRange = ref('')
const params = reactive({
  siteId: '',
  list: []
})
//图表格数据
const tableLoading = ref(false)
const tableData = ref([])
const chartData = ref([])
const overview = ref({
  visitorCount: 0,
  viewCount: 0
})
const getTableData = async () => {
  tableLoading.value = true
  params.siteId = store.state.site.currentSite?.id
  try {
    let res = await getStationPvAndUv(params)
    if (res.code === 20000) {
      tableData.value = res.data
      chartData.value = res.data
      overview.value.visitorCount = res.data.reduce((sum, item) => sum + item.visitorCount, 0)
      overview.value.viewCount = res.data.reduce((sum, item) => sum + item.viewCount, 0)
    }
  } catch {
    tableLoading.value = false
  }
  tableLoading.value = false
}

// 时间范围按钮组与显示类型按钮组的映射关系
//单日只能按时，默认按时。
//1-7日可按日，默认按日。
//7-30天可按日、周，默认按日
//1月-3月可按日、周、月，默认按周
//3月-1年可按日、周、月，默认按月
//1年-2年可按日、周、月、年，默认按月
//大于2年可按日、周、月、年，默认按年
const btnMap = reactive({
  0: { range: [0], default: 0 },
  1: { range: [1], default: 1 },
  2: { range: [1], default: 1 },
  3: { range: [1], default: 1 }
})
watch(xAxisType, newVal => {
  if (dateRange.value && dateRange.value[0]) {
    const timeSegments = getTimeSegments(dateRange.value[0], dateRange.value[1], newVal)
    params.list = timeSegments
    fieldList.value[0] = {
      title: xAxisTypeList.value[xAxisType.value].label,
      name: 'key',
      width: 200
    }
    getTableData()
  }
})
//表格数据变化
watch(
  chartData,
  newVal => {
    option.xAxis[0].data = newVal.map(item => item['key'])
    //找出已选指标的序号和name
    const checked = checkOptions.value.filter(item => checkList.value.includes(item.value))
    checked.forEach(item => {
      const { value, name } = item
      option.series[value].data = newVal.map(item => item[name])
    })
    //防止线条乱飞，重新绘制图表
    echarts.dispose(myChart.value)
    myChart.value = echarts.init(chart.value)
    myChart.value.setOption(option)
  },
  { deep: true }
)
//x轴坐标名称
const dataLabel = ref({
  viewCount: '浏览量(PV)',
  visitorCount: '访客量(UV)'
})
//指标选项
const checkOptions = ref([
  { label: '浏览量(PV)', value: 0, name: 'viewCount' },
  { label: '访客量(UV)', value: 1, name: 'visitorCount' }
])
//选中的指标数组
const checkList = ref([0, 1])
//选中指标��化。然后去改变series内Y轴配置的show属性
watch(checkList, (newVal, oldVal) => {
  const add = newVal.filter(item => !oldVal.includes(item))
  if (add.length > 0) {
    if (process.env.NODE_ENV === 'development') console.log('新增指标:', add)
    let i = add[0]
    let { name, label } = checkOptions.value[i]
    let data = chartData.value.map(item => item[name])
    option.series[i].data = data
    option.legend.data.push(label)
  } else {
    const cacle = oldVal.filter(item => !newVal.includes(item))
    if (process.env.NODE_ENV === 'development') console.log('取消指标:', cacle)
    let idx = cacle[0]
    option.series[idx].data = null
    let { label } = checkOptions.value[idx]
    option.legend.data = option.legend.data.filter(item => item != label)
  }
  myChart.value.setOption(option)
})
//站点切换
const handleChangeSite = val => {
  params.siteId = val
  getTableData()
}
//自定义图表类型切换
const chartType = ref('line')
const changeChart = (type, boundaryGap) => {
  chartType.value = type
  option.series.forEach(item => {
    item.type = type
  })
  option.xAxis[0].boundaryGap = boundaryGap
  myChart.value.setOption(option)
}
//图表配置及初始化
let myChart = ref(null)
const chart = ref(null)
const option = reactive({
  grid: {
    left: '50px',
    right: '80px'
  },
  tooltip: {
    trigger: 'axis'
  },
  legend: {
    data: ['浏览量(PV)', '访客量(UV)'],
    bottom: 0
  },
  calculable: true,
  xAxis: [
    {
      type: 'category',
      boundaryGap: false,
      data: chartData.value.map(item => item['key'])
    }
  ],
  yAxis: [
    {
      type: 'value',
      position: 'left',
      axisLine: {
        show: true
      },
      splitArea: {
        show: true, //分割区域
        areaStyle: {
          color: ['#F8F8F8', '#fff']
        }
      },
      splitNumber: 5
    }
  ],
  series: [
    {
      name: '浏览量(PV)',
      type: 'line',
      symbol: 'circle',
      symbolSize: 8,
      smooth: false,
      itemStyle: {
        color: '#4d99f2'
      },
      lineStyle: {
        color: '#4d99f2'
      },
      data: chartData.value.map(item => item['viewCount']),
      yAxisIndex: 0
    },
    {
      name: '访客量(UV)',
      type: 'line',
      symbol: 'circle',
      symbolSize: 8,
      smooth: false,
      itemStyle: {
        color: '#2cbf77'
      },
      lineStyle: {
        color: '#2cbf77'
      },
      data: chartData.value.map(item => item['visitorCount']),
      yAxisIndex: 0
    }
  ]
})
const fieldList = ref([
  {
    title: '按时',
    name: 'key',
    width: 200
  },
  {
    title: '浏览量(PV)',
    name: 'viewCount'
  },
  {
    title: '浏览量占比',
    name: 'viewPercent'
  },
  {
    title: '访客量(UV)',
    name: 'visitorCount'
  },
  {
    title: '访客量占比',
    name: 'visitorPercent'
  }
])
const getTimeSegments = (startDate, endDate, xAxisType) => {
  const result = []

  if (xAxisType === 0) {
    // 按时保持6个点不变
    const now = new Date()
    const actualEndDate = endDate.getTime() > now.getTime() ? now : endDate
    const totalTime = actualEndDate.getTime() - startDate.getTime()
    const segmentDuration = Math.floor(totalTime / 6)

    for (let i = 0; i < 6; i++) {
      const segmentStart = startDate.getTime() + segmentDuration * i
      const segmentEnd = i === 5 ? actualEndDate.getTime() : startDate.getTime() + segmentDuration * (i + 1)

      result.push({
        startTime: segmentStart,
        endTime: segmentEnd,
        key: dayjs(segmentStart).format('HH:mm')
      })
    }
  } else {
    // 按日显示
    const totalDays = dayjs(endDate).diff(startDate, 'day')
    
    // 遍历每一天
    for (let i = 0; i <= totalDays; i++) {
      const segmentStart = dayjs(startDate).add(i, 'day')
      const segmentEnd = dayjs(startDate).add(i + 1, 'day')

      result.push({
        startTime: segmentStart.valueOf(),
        endTime: segmentEnd.valueOf(),
        key: segmentStart.format('MM/DD')
      })
    }
  }

  return result
}
watch(
  dateType,
  newVal => {
    dateRange.value = getStartAndEndTimes(newVal)
  },
  { deep: true, immediate: true }
)
watch(dateRange, newVal => {
  if (dateRange.value && dateRange.value[0]) {
    let timeRangeType = getTimeDifference(newVal[0], newVal[1])

    // 获取对应的范围和默认值
    if (!timeRangeType && timeRangeType !== 0) {
      timeRangeType = 6
    }
    const { range, default: defaultXAxisType } = btnMap[timeRangeType]

    // 更新xAxisTypeList
    xAxisTypeList.value.forEach((item, index) => {
      item.disabled = !range.includes(index)
    })

    // 如果当前 xAxisType 不在允许范围内，设置为默认值
    if (!range.includes(xAxisType.value)) {
      xAxisType.value = defaultXAxisType
    }

    // 处理时间段
    const timeSegments = getTimeSegments(dateRange.value[0], dateRange.value[1], xAxisType.value)

    // 更新查询参数
    params.list = timeSegments
  } else {
    params.list = []
  }
  getTableData()
})

onMounted(() => {
  dateRange.value = getStartAndEndTimes(0)
  myChart.value = echarts.init(chart.value)
  myChart.value.setOption(option)
  window.onresize = function () {
    myChart.value.resize()
  }
})
</script>

<style lang="scss" scoped>
.page-view {
  padding: 20px;
  background: #ffffff;
  .date-select {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .select-left {
      display: flex;
      align-items: center;
      span {
        margin-right: 10px;
      }
      .date-picker {
      }
      ::v-deep .el-input__wrapper {
        margin-left: 20px;
        width: 340px;
      }
    }
    .select-right {
    }
  }
  .data-content {
    padding: 40px 0;
    .data-card {
      display: flex;
      justify-content: space-around;
      border-bottom: 1px solid #e4e4e4;
      .card-item {
        display: flex;
        flex-direction: column;
        .label {
          margin-bottom: 14px;
          font-size: 14px;
          color: #aaaaaa;
        }
        .num {
          margin-bottom: 20px;
          font-size: 32px;
          color: #333333;
        }
      }
    }
    .chart-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin: 25px 0 0;
      .point-select {
        display: flex;
        align-items: center;
        .el-checkbox {
          margin: 0 5px;
        }
        span {
        }
      }
      .chart-btns {
        height: 32px;
        width: 64px;
        box-sizing: border-box;
        border: var(--el-border);
        border-radius: 4px;
        display: flex;
        overflow: hidden;
        a {
          display: flex;
          width: 50%;
          height: 100%;
          align-items: center;
          justify-content: center;
        }
        a.active {
          background-color: $mainColor;
          i {
            color: #fff;
          }
        }
      }
    }
  }
  .table-content {
    .page-pagination {
      display: flex;
      justify-content: flex-end;
      padding: 15px;
      background: #ffffff;
    }
  }
}
::v-deep .el-table th.el-table__cell {
  background-color: #f2f2f2;
  color: #333333;
}
</style>
